<template>
  <div class="setting-container">
    <div class="app-container">
      <!-- 卡片组件 -->
      <el-card class="box-card">
        <!-- 使用 Tabs 组件完成标签页布局 -->
        <el-tabs v-model="activeName">
          <el-tab-pane label="角色管理" name="first" class="tab-pane">
            <!-- 新增角色按钮 -->
            <el-row style="height:60px">
              <el-button icon="el-icon-plus" size="small" type="primary" @click="addRoleBtnFn">新增角色</el-button>
            </el-row>
            <!-- 使用 Table 组件实现用户角色的渲染 -->
            <el-table :data="rolesList" border style="width: 100%">
              <!-- type="index" 默认展示的就是循环的索引值,prop="对象字段"会取值在当前列 -->
              <!-- <el-table-column type="index" label="序号" width="120" /> -->

              <el-table-column v-slot="scope" label="序号" width="120">
                <span>{{ (query.page - 1 ) * query.pagesize + scope.$index + 1 }}</span>
              </el-table-column>

              <el-table-column label="角色名" width="240" prop="name" />
              <el-table-column label="描述" prop="description" />
              <el-table-column label="操作">
                <template slot-scope="scope">
                  <el-button size="small" type="success" @click="setRoles(scope.row)">分配权限</el-button>

                  <!-- scope.row 拿到的是数组里遍历的这行的对应数据对象 -->
                  <el-button size="small" type="primary" @click="editRoles(scope.row)">编辑</el-button>
                  <el-button size="small" type="danger" @click="delRoles(scope.row)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>

            <!-- 分页区域
            扩展: 页面上有些字, 如果发现用的是组件, 可能是组件里自带的
            :current-page 外面影响组件内默认选中的是第几页而已 (UI层受到影响)
            @current-change 内部点击页面切换, 会回调此事件的处理函数执行(拿到点击的页码数)
            :page-sizes 一共可以修改每页显示多少条选项
            :page-size 受到右侧数值的影响, ui层下拉菜单默认选中哪个看传入的数字
            @size-change 页面用户选择了下拉菜单条数, 触发此事件
            记住: Pagination只是封装了组件标签+点击事件交互 (数据逻辑, 需要我们自己在事件处理函数中, 自己写, 还有自己发请求)

            Pagination产生页码思路:
            (1): total 总数据条数传入
            (2): page-size 每页显示多少条(默认10)
            -->
            <el-pagination :current-page="query.page" :page-sizes="[10, 20, 30, 50]" :page-size="query.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
          </el-tab-pane>
          <el-tab-pane label="公司信息" class="tab-pane">
            <el-alert title="对公司名称、公司地址、营业执照、公司地区的更新，将使得公司资料被重新审核，请谨慎修改" type="info" show-icon :closable="false" />
            <el-form :model="companyForm" label-width="120px" style="margin-top:50px">
              <el-form-item label="公司名称" prop="name">
                <el-input v-model="companyForm.name" disabled style="width:400px" />
              </el-form-item>
              <el-form-item label="公司地址" prop="companyAddress">
                <el-input v-model="companyForm.companyAddress" disabled style="width:400px" />
              </el-form-item>
              <el-form-item label="邮箱" prop="mailbox">
                <el-input v-model="companyForm.mailbox" disabled style="width:400px" />
              </el-form-item>
              <el-form-item label="备注" prop="remarks">
                <el-input v-model="companyForm.remarks" type="textarea" :rows="3" disabled style="width:400px" />
              </el-form-item>
            </el-form>
          </el-tab-pane>
        </el-tabs>
      </el-card>

      <!-- 新增角色-弹窗+表单 -->
      <el-dialog :title="isEdit ? '编辑角色' : '新增角色'" :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="showDialog" @close="cancleAddRoles">
        <el-form ref="roleForm" :model="roleForm" :rules="roleRules" label-width="100px">
          <el-form-item label="角色名称" prop="name">
            <el-input v-model="roleForm.name" />
          </el-form-item>
          <el-form-item label="角色描述" prop="description">
            <el-input v-model="roleForm.description" />
          </el-form-item>
        </el-form>

        <!-- 底部 -->
        <el-row slot="footer" type="flex" justify="center">
          <el-col :span="6">
            <el-button size="small" @click="cancleRoles">取消</el-button>
            <el-button size="small" type="primary" @click="roleSubmit">确定</el-button>
          </el-col>
        </el-row>
      </el-dialog>

      <!-- 权限点分配-弹窗 -->
      <el-dialog title="权限点分配" :visible.sync="permissionShowDialog">
        <assignPermission ref="assignPer" :permission-show-dialog.sync="permissionShowDialog" :permission-list="permissionList" @setPerIdsEV="updatePermissionFn" />
      </el-dialog>
    </div>
  </div>
</template>

<script>
import {
  getRoleListAPI,
  getCompanyInfoAPI,
  addRoleAPI,
  getRoleDetailByIdAPI,
  udateRoleDetailByIdAPI,
  delRoleAPI,
  assignPermissionAPI
} from '@/api/setting'
import { mapGetters } from 'vuex'

import assignPermission from './assignPermission.vue'
import { getPermissionListAPI } from '@/api/permission'
import { tranListToTreeData } from '@/utils'

export default {
  components: {
    assignPermission
  },
  data() {
    return {
      activeName: 'first',
      query: {
        // 角色列表查询参数
        page: 1, // 当前页面
        pagesize: 10 // 页面显示的条数
      },
      rolesList: [], // 角色列表
      total: 0, // 角色数据总条数
      companyForm: {
        // 公司数据对象
        name: '', // 名字
        companyAddress: '', // 地址
        mailbox: '', // 邮箱
        remarks: '' // 备注
      },
      showDialog: false, // 新增角色-弹窗
      roleForm: {
        // 添加角色-表单数据对象
        name: '',
        description: ''
      },
      roleRules: {
        // 添加角色-表单验证
        name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
        description: [{ required: true, message: '角色描述不能为空', trigger: 'blur' }]
      },
      isEdit: false, // 添加角色(false)/编辑角色(true)
      permissionShowDialog: false, // 权限点分配->弹窗是否出现
      permissionList: [], // 权限点列表数组
      clickRoleId: '' // 分配权限点之前, 点击那行角色ID(中转)
    }
  },
  computed: {
    ...mapGetters(['companyId'])
  },
  created() {
    this.getRoleListFn()
    this.getCompanyInfoFn()
    this.getPermissionListFn()
  },
  methods: {
    // 获取-全部角色列表
    async getRoleListFn() {
      const res = await getRoleListAPI(this.query)
      // console.log(res)
      this.rolesList = res.data.rows

      // 分页可以让后端配合(传递页码给后台), 只会返回对应一段数据和总数
      // 或者后端返回所有数据, 分页在前端截取数组
      this.total = res.data.total // 总数
    },
    // 获取-公司信息
    async getCompanyInfoFn() {
      const res = await getCompanyInfoAPI(this.companyId)
      // console.log(res)
      this.companyForm = res.data
    },
    // 新增角色 -> 点击事件 -> 弹窗出现(???)
    addRoleBtnFn() {
      this.showDialog = true // 弹窗出现
      this.isEdit = false // 添加角色(false)
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(size) {
      this.query.pagesize = size
      this.getRoleListFn()
    },

    // 当前页面发生改变时触发
    handleCurrentChange(currentPage) {
      // currentPage - 点击的当前页码的数字
      this.query.page = currentPage
      this.getRoleListFn()
    },

    // 设置角色(权限点分配)->点击事件
    async setRoles(roleObj) {
      // roleObj 角色对象
      this.clickRoleId = roleObj.id
      this.permissionShowDialog = true
      // 获取这行角色的详情数据
      const res = await getRoleDetailByIdAPI(roleObj.id)
      // console.log(res)
      this.$refs.assignPer.$refs.perTree.setCheckedKeys(res.data.permIds)
      // 因为node-key="id"对象id字段
      // 传入默认选中的数组里, 必须是id值
    },

    // 获取-权限点列表
    async getPermissionListFn() {
      const res = await getPermissionListAPI()
      // console.log(res)
      this.permissionList = tranListToTreeData(res.data, '0')
    },

    // 弹窗 - 分配角色点 - 确定点击事件
    async updatePermissionFn(permIdsArr) {
      const res = await assignPermissionAPI(this.clickRoleId, permIdsArr)
      console.log(res)
      if (res.success) this.$message.success(res.message)
      else this.$message.error(res.message)
    },

    // 编辑角色
    async editRoles(obj) {
      // obj表格行对应数据对象(有name有描述有id)
      const res = await getRoleDetailByIdAPI(obj.id)
      // console.log(res)
      this.showDialog = true
      this.roleForm = res.data // roleForm变量对象地址直接换掉->影响标签里使用的地方才做了数据回显
      this.isEdit = true // 编辑角色(true)
    },

    // 删除角色
    delRoles(obj) {
      this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          // 确定
          // 调用接口:
          await delRoleAPI(obj.id)

          this.$message({
            type: 'success',
            message: '删除成功!'
          })

          // 判断当前数据的长度是否等于 1
          if (this.rolesList.length === 1) {
            this.query.page--
            // 如果是第一页的最后一条
            if (this.query.page <= 0) {
              this.query.page = 1
            }
          }

          this.getRoleListFn() // 刷新列表
        })
        .catch(() => {
          // 取消
          this.$message({
            type: 'info',
            message: '已取消删除'
          })
        })
    },

    // 弹窗-关闭回调函数
    cancleAddRoles() {
      // 弹窗关闭
      this.showDialog = false

      // 置空弹窗内容
      this.$refs.roleForm.resetFields()

      // 手动置空
      const dataObj = this.$options.data() // 执行了一次export default里data选项函数, 里return一个初始对象到这里
      this.roleForm = dataObj.roleForm // 初始roleForm取出来, 替换给运行时组件对象(达到回归初始化空字符串目的)
    },

    // 弹窗 - 新增角色-确定点击事件
    roleSubmit() {
      this.$refs.roleForm.validate(async valid => {
        if (valid) {
          // 都通过校验了
          if (this.isEdit) {
            // 判断: 是新增状态还是编辑状态
            // 调用更新角色的 API
            const res = await udateRoleDetailByIdAPI(this.roleForm)
            console.log(res)
          } else {
            // 调用新增角色的 API
            const res = await addRoleAPI(this.roleForm)
            console.log(res)
          }

          // 重新获取全部角色列表
          this.getRoleListFn()
          // 弹窗关闭
          this.showDialog = false
          // console.log(this.$refs.roleForm.resetFields)// 打印此方法点击进入source看关键源码
          // resetFields()在使用的时候, model的对象和prop指定的属性, 尝试取出默认值, 覆盖给表单
          // 原因: (你上来点击编辑, 直接把roleForm变量地址改变了->新的对象(带值))
          // 等待重置的时候, 拿到的默认值就是编辑时候的值, 重置失败
          // 解决: 不能依赖这个方法了(但是还可以使用它取消校验报错的红色提示文字), 手动清空
          this.$refs.roleForm.resetFields()

          // console.log(this.$refs.roleForm.resetFields)
          // 手动置空弹窗内容:
          // this.roleForm.name = ''
          // this.roleForm.description = ''

          // 扩展: 如果上面这种属性太多, 想要快速恢复成初始data数据,用下面
          const dataObj = this.$options.data() // 执行了一次export default里data选项函数, 里return一个初始对象到这里
          this.roleForm = dataObj.roleForm // 初始roleForm取出来, 替换给运行时组件对象(达到回归初始化空字符串目的)

          // 其实 this.roleForm = {} 也可以
          // v-model双向数据绑定, 视图值变化会给roleForm对象设置值, 但是发现属性不在会动态添加(隐式)
          // 但是尽量还是让对象先有属性, 语义更明确
        }
      })
    },
    // 新增角色-取消点击事件
    cancleRoles() {
      // 关闭弹窗
      this.showDialog = false
    }
  }
}
</script>

<style lang="scss" scoped>
.box-card {
  padding: 10px 30px;
}

.tab-pane {
  padding: 20px;
}

.el-pagination {
  text-align: center;
  margin-top: 20px;
}
</style>
